/**
 ============================================================================
 Author     : Jonathan MERCIER
 Version    : 0.1
 License    : GPL v3+
 Copyright  : (c)Jonathan MERCIER (read doc for more information)

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.

 Description :
 ============================================================================
 */
 
import tango.io.Stdout          : Stdout;
import tango.io.device.File     : File;
import tango.io.stream.TextFile : TextFileInput;
import tango.io.stream.Patterns : Patterns;
import metatool                 : printDebug;
import tango.io.device.Array;
import tango.text.Regex;

class Parser {
private:
    File        parseFile;
    char[][]    enzrev;
    char[][]    enzirrev;
    char[][]    metext;
    char[][]    metint;
    char[][]    cat;
    double[]    matrix; //stoichiometric
    char[][][] test;
    /**
     * isEmpty private method for parse a string return true or false
     * currently they are some bug with Regexp module will be fixed
     */
    bool isEmpty(char[] str){
        bool badString      = true;
        bool continueParse  = true;
        int i               = 0;
        
        while(continueParse){
            if(i == str.length )
                continueParse = false;
            else if(str[i] != ' '){
                continueParse   = false;
                badString       = false;
            }
        } 
        return badString;
    }
    /**
     * splitLine
     * Params:
     *  line        line to split
     *  patternChar pattern used for split
     */
    char[][] splitLine(char[] line, char[] patternChar){
        int     i       = 0;
        char[][] array;
        auto pattern = new Patterns (patternChar, new Array(line));
        //each word is put in array
        foreach(word; pattern){
            printDebug(word);
            array.length = i+1;
            array[i] = word;
            i++;
        }
        return array;
    }
    /**
     * addWord private method use for slice line and put word in array
     * Params:
     *  array   array send by reference
     *  input   object for parse file
     */
    TextFileInput addWord(out char[][] array, TextFileInput input){
        char[]  word;
        char[] line;
        while( input.readln(line) && (!isEmpty(line)) ){
            printDebug("Scaning line: "~line);
            array           = splitLine(line, r"\s");
        }
        return input;
    }
    
    
    /**
     * getReaction
     * Params:
     *  array   array to store data
     *  input   object for parse file
     */
    TextFileInput getReaction(out char[][] array, TextFileInput input){
        char[]  word;
        char[] line;
        while( input.readln(line) && (!isEmpty(line)) ){
            printDebug("Scaning line: "~line);
            
        }
    
        return input;
    }
    
public:
    /**
     * Constructor
     * Params:
     *  parseFile
     */
    this(File parseFile){
        printDebug("parser object is createds");
        this.parseFile  = parseFile;
        printDebug("parse file: "~parseFile.toString);
    }
    /**
     * Constructor
     * Params:
     *  parsePath
     */
    this(char[] parsePath){
        printDebug("parser object is createds");
        parseFile   = new File(parsePath);
        printDebug("parse file: "~parsePath);
    }
    /**
     * Destructor
     */
    ~this(){
        
    }
    /**
     * Getter attribute for parseFile
     */
     File getParseFile(){
        return parseFile;
     }
    /**
     * Getter attribute for enzrev
     */
    char[][] getEnzrev(){
        return enzrev[0..$];
    }
    /**
     * Getter attribute for enzirev
     */
    char[][] getEnzirrev(){
        return enzirrev[0..$];
    }
    /**
     * Getter attribute for metext
     */
    char[][] getMetext(){
        return metext[0..$];
    }
    /**
     * Getter attribute for metint
     */
     char[][] getMetint(){
        return metint[0..$];
    }
    /**
     * Getter attribute for cat
     */
    char[][] getCat(){
        return cat[0..$];
    }
    /**
     * Getter attribute for matrix
     */
     double[] getMatrix(){
        return matrix[0..$];
    }
    /**
     * Setter attribute for parseFile
     */
     void setParseFile(File parseFile){
        this.parseFile = parseFile;
     }
    /**
     * run controller method
     */
    void run(){
        printDebug("Parsing ...");
        auto input          = new TextFileInput(parseFile.toString);
        auto enzevRegexp    = new Regex(r"^-ENZREV");
        auto enzirrevRegexp = new Regex(r"^-ENZIRREV");
        auto metextRegexp   = new Regex(r"^-METEXT");
        auto metintRegexp   = new Regex(r"^-METINT");
        auto catRegexp      = new Regex(r"^-CAT");
        auto commentRegexp  = new Regex(r"^#");
        bool continueParsing= true;
        char[] line;
        
        //Read file line by line
        while (input.readln(line) && continueParsing){
            if(enzevRegexp.test(line)){
                printDebug("token -ENZREV found");
                input = addWord(enzrev, input);
            }
            else if(enzirrevRegexp.test(line)){
                printDebug("token -ENZIRREV found");
                input = addWord(enzirrev, input);
            }
            else if(metextRegexp.test(line)){
                printDebug("token -METEXT found");
                input = addWord(metext, input);
            }
            else if(metintRegexp.test(line)){
                printDebug("token -METINT found");
                input = addWord(metint, input);
            }
            else if(catRegexp.test(line)){
                printDebug("token -CAT found");
                input = getReaction(cat, input);
                continueParsing = false;
            }
            else if(commentRegexp.test(line)){
                printDebug("Comment: "~line);
            }
            
        }
        printDebug("Parsing: Done.");
        matrix.length = (enzrev.length + enzirrev.length)*(metext.length + metint.length);
        matrix[] = 0;
        
        test.length =1;
        test[0].length =1;
        test[0][0] = "jhjkhm";
        test[0].length =2;
        test[0][1] = "olpkpokpo";
        test[0].length =3;
        test[0][2] = "jhjkhm";
        test[0].length =4;
        test[0][3] = "olpkpokpo";
        test[0].length =5;
        test[0][4] = "jhjkhm";
        foreach(words; test){
            foreach(word; words){
                printDebug(word);
            }
        }
    }
}
